package com.utils;
 

import com.cw.MergerSort;
import junit.framework.TestCase;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class MemoryTest extends TestCase{
	private Runtime run;
	private long startMem,endMem,startTime,endTime;
	private static String FORMAT="memory total:%s,free:%s,use:%s";
	
	@Override
	protected void setUp() throws Exception {
		run=Runtime.getRuntime();
		run.gc();
		startMem=getMemory();
		startTime=getTime();
	}

	/**
	 * 测试一个方法所消耗的内存以及时间
	 * @throws ClassNotFoundException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 */
	public void testMemory() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
		int []arr = {9,8,7,6,5,4,3,2,1};
		invokePrivateMethod(arr);
		endMem=getMemory();
		endTime = getTime();
		System.out.println("memory used:"+ByteUnitConversionUtil.convert(endMem-startMem, ByteUnitConversionUtil.Units.MB));
		System.out.println("程序运行时间： "+(endTime-startTime)+"ms");
	}

	/**
	 * 反射调用私有方法
	 * @param arr
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 */
	private void invokePrivateMethod(int[] arr) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
		//通过Class的静态方法forName加载Person
		Class cls=Class.forName("com.cw.MergerSort");
//		Class cls=Class.forName("com.flydean.MergeSort");
		//实例化对象的方法
		Object o=cls.newInstance();
		/*
		 * 在类的外部通过反射调用私有方法会破坏封装性如不是必要操作或设计需求，不建议这样做。
		 */
		Method m= cls.getDeclaredMethod("sort",int[].class);
//		Method m= cls.getDeclaredMethod("doMergeSort",int[].class,int.class,int.class);
		//在访问私有方法前设置访问操作(不设置直接调用会报错)
		m.setAccessible(true);
		m.invoke(o,arr);
//		m.invoke(o,arr,0,arr.length-1);
		System.out.println(Arrays.toString(arr));
	}

	/**
	 * 获取开始/结束内存
	 * @return
	 */
	private long getMemory(){
		long total=run.totalMemory();
		long free=run.freeMemory();
		System.out.println(String.format(FORMAT,
				ByteUnitConversionUtil.convert(total,ByteUnitConversionUtil.Units.MB),
				ByteUnitConversionUtil.convert(free,ByteUnitConversionUtil.Units.MB),
				ByteUnitConversionUtil.convert(total-free,ByteUnitConversionUtil.Units.MB)));
		return total-free;
	}

	/**
	 * 获取开始/结束时间
	 * @return
	 */
	public static long getTime() {
		return System.currentTimeMillis();
	}
}